#ifndef TREEMODEL_H
#define TREEMODEL_H

#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QStandardItemModel>
#include <QImage>

#include "Common.h"
#include "CardInfo.h"
#include "knowledgebase.h"

class TreeItem;
class Deck;
class ITreeItemFactory;


class TreeModel : public QAbstractItemModel
{
		Q_OBJECT

	private:

		class ModelResetHelper;

	public:
		TreeModel(QObject *parent = 0);
		~TreeModel();

		QVariant 		data(			const QModelIndex &index, int role =Qt::DisplayRole) const;

		QVariant		displayRoleData(TreeItem* item, TreeItem::DataColumn col) const;
		QVariant		editRoleData(TreeItem* item, TreeItem::DataColumn col) const;

		QVariant 		headerData(		int section, Qt::Orientation orientation,
		                                int role = Qt::DisplayRole) const;

		QModelIndex		index(			int row, int column,
		                                const QModelIndex &parent = QModelIndex()) const;
		QModelIndex		parent(			const QModelIndex &index) const;

		int				rowCount(		const QModelIndex &parent = QModelIndex()) const;

		int				columnCount(		const QModelIndex &parent = QModelIndex()) const;

		Qt::ItemFlags 	flags(			const QModelIndex &index) const;

		bool 			setData(			const QModelIndex &index, const QVariant &value,
		                                    int role = Qt::EditRole);

		//void			setImage(       const QModelIndex& index, QImage)

		bool 			setHeaderData(	int section, Qt::Orientation orientation,
		                                const QVariant &value, int role = Qt::EditRole);

		bool 			insertRows(		int position, int rows,
		                                const QModelIndex &parent = QModelIndex());

		bool 			removeRows(		int position, int rows,
		                                const QModelIndex &parent = QModelIndex());

		bool 			cut(				int position, int rows,
		                                    const QModelIndex &parent = QModelIndex());

		bool 			paste(			int position, int rows,
		                                const QModelIndex &parent = QModelIndex());

		void				getDueCardsDepthFirst(const QModelIndex&, CardInfo&) const;

		bool				hasDueCards() const;

		void				invertItem(		const QModelIndex& index);

		QList<QString>	getLineage(const QModelIndex&) const;

		CardInfo			getCardInfo(const QModelIndex& index);

		Card*				getCard(const QModelIndex& index);

		TreeItem*			getItemByUuid(const QUuid& uuid) const;
		TreeItem*			getItem(const QModelIndex &index) const;

		unsigned int		getNumCards(const QModelIndex &index) const;

		QModelIndex			indexOf(TreeItem* item) const;

		void				notifyItemUpdate(TreeItem* item);

		////// DEBUG FUNCTIONS GO HERE //////
		int				getDueDate(		const QModelIndex&);
		/////////////////////////////////////

		//void				createAndInsertNode(TreeItem* parentItem, int insertionPosition);


	signals:

		void				treeItemChanged(const TreeItem& item); //to be implemented
		void				newTreeCreated();

	public slots:

		//void				serialize();
		void				convertSelectionToCards(const QModelIndex&, bool);
		CardInfo			getNextDueCard()	const;

		void				pauseBranch(const QModelIndex&, bool);

		void				convertCardToTwig(const QModelIndex&);

		void				loadLastFile();
		bool				saveTreeAs();
		bool				saveChanges();
		void				createTree();
		void				loadNewFile();
		bool				confirmApplicationExit();

		ITreeItemFactory*	treeItemFactory() const;
		void				setTreeItemFactory(ITreeItemFactory* factory);

	private:

		void				setBranchPaused(TreeItem*, bool paused);

		void				loadFromFile(const QString path);
		void				saveToFile(const QString path);

		QString				lastLoadedFile() const;
		void				setLastLoadedFile(const QString& value);

		void				clearTree();
		bool				askModelDropConfirmation(); //returns true only if user confirms exit
		bool				hasUnsavedChanges() const;
		void				markUnsaved();
		void				resetUnsavedFlag();

		ITreeItemFactory*	currentOrDefaultTreeItemFactory() const;
		//TreeItem*			createTreeItem(const QVector<QVariant> &data, TreeItem *parent) const;
		//TreeItem*			createTreeItem(TreeItem *parent) const;


	private:

		TreeItem	*		m_pRootItem;
		//Deck	*			m_pDeck;
		TreeItem	*		m_currentReviewCard;
		KnowledgeBase		*m_pKnowledgeBase;
		QString				_currentFileName;
		bool				_unsavedChanges;

		ITreeItemFactory*	m_pTreeItemFactory;
};

#endif
